import time
import datetime
import logging
from .. import tables

class ParseServiceBase(object):

    def __init__(self):
        '''
        '''
        self.trips = []
        self.flat = self.flon = self.fname = self.tlat = self.tlon = self.tname = self.url = self.url_record = self.trip_planner = None

    def parse(self, doc, url, url_rec):
        trip = tables.Trip()
        trip.doc = doc
        trip.url = url
        trip.url_record = url_rec
        trip.url_id = url_rec.id
        return trip


    def parse_itineraries(self, trip, itineraries):
        ''' loop through an array and call parse_itinerary
        '''
        if len(itineraries) > 0:
            trip.success = True
            trip.num_itineraries = len(itineraries)
            best = None
            for i in itineraries:
                itin = self.parse_itinerary(trip, i)
                best = self.best_itinerary(itin, best)
        else:
            trip.success = False


    def parse_itinerary(self, trip, itinerary):
        return itinerary


    def make_trip(self):
        ''' Will build a Trip() DAO object for insertion into the database.  Value assignment is based on attributes assigned to 
            this class (using introspection).  Basically, do a self.from_lat in your PaserService object, and it will makes its way over to 
            the new Trip object returned from this method

            NOTE: stupid way to do this...
        '''

        # use introspection to assign data from this object to the new trip object ... kinda funky, but efficient
        medict = self.__dict__
        tdict  = trip.__dict__
        for k in medict.keys():
            tdict[k] = medict[k]

        # special foreign key handler ... if this url_record is not there (with an id), database will throw and exception when inserting this trip  
        if self.url_record is not None:
            tdict['url_id'] = self.url_record.id

        return trip

    def make_itinerary(self, trip):
        itin = tables.Itinerary()
        trip.itineraries.append(itin)
        return itin


    @classmethod
    def best_itinerary(cls, itin, best):
        ''' compare this itinerary (itin) with the current 'best' itinerary for this trip, using number of transfers, start time and trip length as markers
        '''
        ret_best = best
        if itin is None or itin.transit_time is None or itin.transit_time < 1.0:
            logging.info("best_itinerary: input itin or itin.transit_time is bogus")
        elif best is None:
            itin.best = True
            ret_best = itin
        elif itin.start_time < (best.start_time + datetime.timedelta(minutes=15)):
            if itin.transfers < best.transfers and itin.duration < (int(best.duration) + 10):
                itin.best = True
                best.best = False
                ret_best = itin
            elif itin.transfers == best.transfers and itin.duration < best.duration:
                itin.best = True
                best.best = False
                ret_best = itin

        return ret_best


    @classmethod
    def make_datetime(cls, d, t, date_mask='%m/%d/%Y', time_mask='%I:%M %p'):
        if d is None:
            d = time.strftime(date_mask)
        if t is None:
            t = time.strftime(time_mask)
        ret_val = None
        try:
            ret_val = datetime.datetime.strptime(d + ' ' + t, date_mask + ' ' + time_mask)
        except:
            try:
                date_mask='%m/%d/%Y'
                time_mask='%I:%M %p'
                ret_val = datetime.datetime.strptime(d + ' ' + t, date_mask + ' ' + time_mask)
            except:
                try:
                    date_mask='%m/%d/%y'
                    time_mask='%I:%M %p'
                    ret_val = datetime.datetime.strptime(d + ' ' + t, date_mask + ' ' + time_mask)
                except:
                    pass

        return ret_val


    @classmethod
    def xml_coord(cls, dom):
        ''' return lat, lon from dom element 
        '''
        lat = lon = None
        try:
            lat = dom.getElementsByTagName('lat')[0].firstChild.data
            lon = dom.getElementsByTagName('lon')[0].firstChild.data
        except:
            logging.info("xmlCoord: query of lat/lon threw an exception...might simply be that value doesn't exist in the data")
            pass

        return lat, lon


    @classmethod
    def xml_value(cls, dom, name):
        ''' return value from dom element
        '''
        retVal = None
        try:
            retVal = dom.getElementsByTagName(name)[0].firstChild.data
        except:
            logging.info("xmlValue: query of element '" + name + "' threw an exception...might simply be that value doesn't exist in the data")
            pass
        return retVal 

    @classmethod
    def xml_key_value(cls, dom, target_key, parent_node='entry'):
        ''' finds a node(s) in the dom, who have a key/value pairing, ala <entry><key>X</key><value>Y</value>
        '''
        retVal = None
        try:
            nodes = dom.getElementsByTagName(parent_node)
            for n in nodes:
                key = n.getElementsByTagName('key')[0].firstChild.data
                if target_key in key:
                    retVal = n.getElementsByTagName('value')[0].firstChild.data
                    break
        except:
            logging.info("xml_key_value: query of element '" + target_key + "' threw an exception...might simply be that value doesn't exist in the data")
            pass
        return retVal 


    @classmethod
    def xml_attribute(cls, dom, name, attributeValue, attributeKey='name'):
        ''' finds a node(s) in the dom, who have an attribute name of attributeId, and whose value is attributeValue  
            for example, this call xml_attribute(dom, 'param', 'Min') will return XXX, on the first <param @name="Min">XXX</param> element seen in the dom
        '''
        retVal = None
        try:
            nodes = dom.getElementsByTagName(name)
            for n in nodes:
                if attributeValue in n.getAttribute(attributeKey):
                    retVal = n.firstChild.data 
                    break
        except:
            logging.info("xmlAttribute: query of element '" + name + "' threw an exception...might simply be that value doesn't exist in the data")
            pass
        return retVal 
